﻿using System;
using System.IO;
using System.Text;
using System.Data;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using System.Reflection;
using System.Collections;
using System.Globalization;
using System.Security.Cryptography;
using System.Runtime;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.SqlServer.Server;

namespace PickGold.SqlServer
{
	/// <summary>
	/// 
	/// </summary>
	[Serializable]
	[SqlUserDefinedAggregate(Format.UserDefined, IsInvariantToNulls = true, IsInvariantToDuplicates = false, IsInvariantToOrder = false, IsNullIfEmpty = true, MaxByteSize = SqlUserDefinedAggregateAttribute.MaxByteSizeValue)]
	public sealed class AllCharConcat : IAggregate<SqlString, AllCharConcat>, INullable, IBinarySerialize
	{
		/// <summary>
		private StringBuilder Value;

		/// <summary>
		/// 指示结构是否为 null。此属性为只读。
		/// </summary>
		public bool IsNull
		{
			get
			{
				if (this.Value == null)
					return true;

				return false;
			}
		}

		/// <summary>
		/// Initialize the internal data structures
		/// </summary>
		public void Init()
		{
			this.Value = null;
		}

		/// <summary>
		/// Accumulate the next value, not if the value is null
		/// </summary>
		/// <param name="value"></param>
		public void Accumulate(SqlString value)
		{
			if (value.IsNull)
				return;

			if (this.Value == null)
				this.Value = new StringBuilder(value.Value);
			else
				this.Value.Append(value.Value);
		}

		/// <summary>
		/// Merge the partially computed aggregate with this aggregate.
		/// </summary>
		/// <param name="value"></param>
		public void Merge(AllCharConcat value)
		{
			if (value == null || value.Value == null)
				return;

			if (this.Value == null)
				this.Value = value.Value;
			else
				this.Value.Append(value.Value.ToString());
		}

		/// <summary>
		/// Called at the end of aggregation, to return the results of the aggregation.
		/// </summary>
		/// <returns></returns>
		public SqlString Terminate()
		{
			if (this.Value == null)
				return SqlString.Null;

			return new SqlString(this.Value.ToString());
		}

		void IBinarySerialize.Read(BinaryReader r)
		{
			this.Value = new StringBuilder(r.ReadString());
		}

		void IBinarySerialize.Write(BinaryWriter w)
		{
			if (this.Value != null)
				w.Write(this.Value.ToString());
		}
	}
}
